﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using LightPersist.Exceptions;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using TestDomainModel;
using LightPersist;

namespace LightPersistTests
{
	[TestClass]
	public class IsReadonly_UndoRedo : IsReadonly
	{
		protected override void Reconnect()
		{
			ChangeTransactionWithUndoRedo();
		}
	}

	[TestClass]
	public class IsReadonly : ContextTestsBase
	{
		protected override void Reconnect()
		{
			ChangeTransaction();
		}

		[TestMethod]
		public void Should_return_objects_as_readonly_by_default()
		{
			var item = Context.Create<FakeControl>();
			Assert.IsTrue(item.IsReadonly);
			Root.Children.Add(item);
			Reconnect();
			Assert.IsTrue(item.IsReadonly);
		}

		[TestMethod]
		public void Should_fire_callback_on_trying_to_change_object()
		{
			try
			{
				Context.ObjectChangeRequest += logWriteRequests;
				Assert.AreEqual(0, fired.Count);
				child.Width = 777;
				Assert.AreEqual(1, fired.Count);
				Assert.AreEqual(child, fired[0]);
				child.Width = 778;
				// we does not request eny more for this object, it is already unlocked
				Assert.AreEqual(1, fired.Count);
			}
			finally
			{
				Context.ObjectChangeRequest -= logWriteRequests;
			}
		}

		[TestMethod]
		public void Should_allow_changing_by_default_and_reser_is_readonly_on_change()
		{
			Assert.IsTrue(child.IsReadonly);
			child.Width = 777;
			Assert.AreEqual(777, child.Width);
			Assert.IsFalse(child.IsReadonly);
			Reconnect();
			Assert.AreEqual(777, child.Width);
			Assert.IsTrue(child.IsReadonly);
		}

		[TestMethod]
		public void Should_allow_to_disable_changing_using_callback()
		{
			try
			{
				Context.ObjectChangeRequest += disableChanginOfChildren1;
				Assert.IsTrue(child.IsReadonly);
				Throws<ObjectIsReadonlyException>(delegate
				{
					child.Width = 777;
				});
				NotThrows(() => tr.CommitTransaction());
			}
			finally
			{
				Context.ObjectChangeRequest -= disableChanginOfChildren1;
			}
		}

		void disableChanginOfChildren1(object sender, WriteRequestedEventArgs e)
		{
			e.IsAllowed = e.Item != child;
		}

		List<ModelBase> fired = new List<ModelBase>();
		void logWriteRequests(object sender, WriteRequestedEventArgs e)
		{
			fired.Add(e.Item);
		}

		[TestMethod]
		public void Should_reset_is_readonly_on_commiting()
		{
			var item = Context.Create<FakeControl>();
			Root.Children.Add(item);
			item.Width = 777;
			Assert.IsFalse(item.IsReadonly);
			tr.CommitTransaction();
			Assert.IsTrue(item.IsReadonly);
			Reconnect();
			Assert.IsTrue(item.IsReadonly);
		}

	}
}
